﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Collections;

namespace PServiceBus.Core.Runtime.Configuration {
    public class ConfigurationParser {

        public static IEnumerable<IDictionary<string, object>> Process(string filename, string sourceAttribute = "configSource") {
            var mainPath = AppDomain.CurrentDomain.BaseDirectory.Replace("\\", "/");
            var pathName = mainPath + filename;
            var doc = new XmlDocument();
            doc.Load(pathName);

            var node = doc.ChildNodes.Cast<XmlNode>().LastOrDefault();

            return ParseMainNode(node);
        }

        static IEnumerable<IDictionary<string, object>> ParseMainNode(XmlNode node, string sourceAttribute = "configSource") {
            if (node == null) yield break;

            var source = node.Attributes[sourceAttribute] != null ? node.Attributes[sourceAttribute].Value : null;

            if (source != null)
                foreach (var dict in Process(source))
                    yield return dict;

            foreach (XmlNode element in node.ChildNodes) {
                var dict = new Dictionary<string, object>();
                ParseNode(element, dict);
                yield return dict;
            }
        }

        static void ParseNode(XmlNode node, Dictionary<string, object> dict) {

            if (node.NodeType == XmlNodeType.Comment || node.NodeType == XmlNodeType.CDATA) return;

            var attributes = new Dictionary<string, object>();
            var name = node.Name;

            foreach (XmlAttribute attribute in node.Attributes) {
                attributes[attribute.Name] = attribute.Value;
            }
            if (dict.ContainsKey(name)) {
                var first = dict[name];
                List<Dictionary<string, object>> list;
                if (typeof(IList).IsAssignableFrom(first.GetType())) {
                    list = dict[name] as List<Dictionary<string, object>>;
                } else {
                    list = new List<Dictionary<string, object>>();
                    list.Add(first as Dictionary<string, object>);
                    dict[name] = list;
                }
                if (attributes.Any())
                    list.Add(attributes);
            } else {
                if (attributes.Any())
                    dict[node.Name] = attributes;
            }

            foreach (XmlNode element in node.ChildNodes) {
                ParseNode(element, dict);
            }
        }

    }
}
